/***********************************************************************************************************************
*                                                                                                                      *
* SPLASH build system v0.1                                                                                             *
*                                                                                                                      *
* Copyright (c) 2013 Andrew D. Zonenberg                                                                               *
* All rights reserved.                                                                                                 *
*                                                                                                                      *
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the     *
* following conditions are met:                                                                                        *
*                                                                                                                      *
*    * Redistributions of source code must retain the above copyright notice, this list of conditions, and the         *
*      following disclaimer.                                                                                           *
*                                                                                                                      *
*    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the       *
*      following disclaimer in the documentation and/or other materials provided with the distribution.                *
*                                                                                                                      *
*    * Neither the name of the author nor the names of any contributors may be used to endorse or promote products     *
*      derived from this software without specific prior written permission.                                           *
*                                                                                                                      *
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED   *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL *
* THE AUTHORS BE HELD LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES        *
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR       *
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE       *
* POSSIBILITY OF SUCH DAMAGE.                                                                                          *
*                                                                                                                      *
***********************************************************************************************************************/

#ifndef CppCompileFlags_h
#define CppCompileFlags_h

/**
	@brief Specifies the level of optimizations to use
 */
class CppOptimizationLevelFlag : public CppCompileFlag
{
public:
	enum CppOptimizationLevel
	{
		OPT_LEVEL_NONE,
		OPT_LEVEL_LOW,
		OPT_LEVEL_HIGH,
		OPT_LEVEL_MAX,
		OPT_LEVEL_SIZE
	};

	CppOptimizationLevelFlag(CppOptimizationLevel level);
	virtual ~CppOptimizationLevelFlag();
	virtual CppCompileFlag* Clone() const;
	virtual std::string toString(const CppToolchain* toolchain);
	
protected:
	CppOptimizationLevel m_level;
};

/**
	@brief Specifies that the target should include debug info
 */
class CppDebugInfoFlag : public CppCompileFlag
{
public:
	CppDebugInfoFlag();
	virtual ~CppDebugInfoFlag();
	virtual CppCompileFlag* Clone() const;
	virtual std::string toString(const CppToolchain* toolchain);
};

/**
	@brief Put each function in its own sectoin
 */
class CppFunctionSectionFlag : public CppCompileFlag
{
public:
	CppFunctionSectionFlag();
	virtual ~CppFunctionSectionFlag();
	virtual CppCompileFlag* Clone() const;
	virtual std::string toString(const CppToolchain* toolchain);
};

/**
	@brief Specifies the target machine architecture
 */
class CppMachineFlag : public CppCompileFlag
{
public:
	CppMachineFlag(std::string machine);
	virtual ~CppMachineFlag();
	virtual CppCompileFlag* Clone() const;
	virtual std::string toString(const CppToolchain* toolchain);
	
protected:
	std::string m_machine;
};

/**
	@brief No parameters. Indicates that the object file should not use any absolute addresses.
 */
class CppPositionIndependentCodeFlag : public CppCompileFlag
{
public:
	virtual ~CppPositionIndependentCodeFlag();
	virtual CppCompileFlag* Clone() const;
	virtual std::string toString(const CppToolchain* toolchain);
};


/**
	@brief No parameters. Indicates that we are using OpenMP
 */
class CppOpenMPFlag : public CppCompileFlag
{
public:
	virtual ~CppOpenMPFlag();
	virtual CppCompileFlag* Clone() const;
	virtual std::string toString(const CppToolchain* toolchain);
};

/**
	@brief Specifies whether all symbols should be exported by default or not.
	
	Not supported on Windows platforms.
 */
class CppVisibilityCodeFlag : public CppCompileFlag
{
public:
	CppVisibilityCodeFlag(bool exportAllSymbols);
	virtual ~CppVisibilityCodeFlag();
	virtual CppCompileFlag* Clone() const;
	virtual std::string toString(const CppToolchain* toolchain);
	
protected:
	bool m_exportAllSymbols;
};

/**
	@brief Adds an include directory to the search path
 */
class CppIncludeDirectoryFlag : public CppCompileFlag
{
public:
	CppIncludeDirectoryFlag(std::string path);
	virtual ~CppIncludeDirectoryFlag();
	virtual CppCompileFlag* Clone() const;
	virtual std::string toString(const CppToolchain* toolchain);
	
	std::string GetPath()
	{ return m_path; }
	
protected:
	std::string m_path;
};

/**
	@brief Specifies not to use branch delay slots
 */
class CppNoDelaySlotFlag : public CppCompileFlag
{
public:
	CppNoDelaySlotFlag();
	virtual ~CppNoDelaySlotFlag();
	virtual CppCompileFlag* Clone() const;
	virtual std::string toString(const CppToolchain* toolchain);
};

/**
	@brief Specifies not to use built-in functions
 */
class CppNoBuiltinFlag : public CppCompileFlag
{
public:
	CppNoBuiltinFlag();
	virtual ~CppNoBuiltinFlag();
	virtual CppCompileFlag* Clone() const;
	virtual std::string toString(const CppToolchain* toolchain);
};

/**
	@brief Specifies that divide-by-zero exception sequences should not be generated.
	
	This flag is required for GRAFTON and SARATOGA.
 */
class CppNoZeroCheckFlag : public CppCompileFlag
{
public:
	CppNoZeroCheckFlag();
	virtual ~CppNoZeroCheckFlag();
	virtual CppCompileFlag* Clone() const;
	virtual std::string toString(const CppToolchain* toolchain);
};

/**
	@brief Specifies the C/C++ standard in use
 */
class CppStandardFlag : public CppCompileFlag
{
public:
	enum CppStandard
	{
		CPP_STANDARD_DEFAULT,
		CPP_STANDARD_0X,
		CPP_STANDARD_11,
		CPP_STANDARD_C99
	};

	CppStandardFlag(CppStandard std);
	virtual ~CppStandardFlag();
	virtual CppCompileFlag* Clone() const;
	virtual std::string toString(const CppToolchain* toolchain);
	
protected:
	CppStandard m_standard;
};

/**
	@brief Specifies that profiling / code coverage statistics should be generated
 */
class CppProfilingFlag : public CppCompileFlag
{
public:
	CppProfilingFlag();
	virtual ~CppProfilingFlag();
	virtual CppCompileFlag* Clone() const;
	virtual std::string toString(const CppToolchain* toolchain);
};

//NOTE: When we add macro definition flags, GnuCppToolchain::GetDefaultMacros needs to be updated to parse this

#endif
